package com.whynot.frame.auth.shiro.argument;

import com.alibaba.fastjson.JSON;
import com.whynot.frame.auth.jwt.utils.JWTUtil;
import com.whynot.frame.auth.shiro.annotation.CurrentUser;
import com.whynot.frame.auth.shiro.cache.AuthCache;
import com.whynot.frame.auth.shiro.entities.BaseSysUser;
import com.whynot.frame.auth.shiro.exception.UnauthorizedException;
import com.whynot.frame.basic.util.SpringUtil;
import com.whynot.frame.basic.util.StringUtils;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import java.util.Map;

/**
 * 描述: 增加方法注入，将含有 @CurrentUser 注解的方法参数注入当前登录用户:
 * 作者: chenyao
 * 日期: 2018-01-30.
 * 项目名称: curtain-whynot-shiro-jwt-server
 * 版本: 1.0.0
 * JDK: since 1.8
 */
@Service
public class CurrentUserMethodArgumentResolver implements HandlerMethodArgumentResolver {


    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return   parameter.getParameterType().getInterfaces()[0].isAssignableFrom(BaseSysUser.class)
        && parameter.hasParameterAnnotation(CurrentUser.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

        Map<String,Object> userBean = null;

        String token = webRequest.getHeader("Authorization");
        if(StringUtils.isEmpty(token)){
            return userBean;
        }
        String userName = JWTUtil.getUsername(token);
        userBean = SpringUtil.getBean(AuthCache.class).getUser(userName);
        if (userBean == null) {
            throw new UnauthorizedException("获取用户信息失败");
        }

        //由于在shiro-jwt的jar中没有对应具体的SysUser对象（便于扩展重写接口），所以这里利用反射的机制设置对象
        return JSON.parseObject(JSON.toJSONString(userBean),parameter.getParameterType().newInstance().getClass());

    }
}
